﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MethodWorx.Core.DomainModel;
using System.Xml;
using MethodWorx.CMS.Workflow;

namespace MethodWorx.CMS.Content
{
    [Serializable]
    public class PageTemplate : AggregateRoot
    {
        public string Name { get; set; }
        public string Description { get; set;}
        public bool AllowedAtRoot { get; set; }
        public bool Abstract { get; set; }
        public virtual PageTemplateBindings Bindings { get; set; }
        public virtual PageTemplate Parent { get; set; }
        public string Template { get; set; }
        public bool Deleted { get; set; }
        public string Css { get; set; }
        public string Script { get; set; }
        public DateTime? DatePublished { get; set; }
        public virtual WorkflowConfiguration[] Workflows { get; set; }

        public PageTemplate() 
            : this((pt) => new PageTemplateConstraint [] { },
                   (pt) => new ContentTemplateConstraint [] { },
                   (pt) => new Property [] { })
        {
            this.Bindings = new PageTemplateBindings();
        }

        public PageTemplate(
            Func<PageTemplate, IEnumerable<PageTemplateConstraint>> pageTemplateConstraints,
            Func<PageTemplate, IEnumerable<ContentTemplateConstraint>> contentTemplateConstraints,
            Func<PageTemplate, IEnumerable<Property>> properties)
        {
            if (pageTemplateConstraints == null)
                throw new ArgumentNullException("pageTemplateConstraints");

            if(contentTemplateConstraints == null)
                throw new ArgumentNullException("contentTemplateConstraints");

            if (properties == null)
                throw new ArgumentNullException("properties");

            this.PageTemplateConstraints =
                new PageTemplateConstraintCollection(this, pageTemplateConstraints);

            this.ContentTemplateConstraints = 
                new ContentTemplateConstraintCollection(this, contentTemplateConstraints);

            this.Properties = new PageTemplatePropertyCollection(this, properties);
        }

        public PageTemplateConstraintCollection PageTemplateConstraints { get; private set; }
        public ContentTemplateConstraintCollection ContentTemplateConstraints { get; private set; }
        public PageTemplatePropertyCollection Properties { get; private set; }

        private class FlattenedTemplate
        {
            public Guid Id { get; set; }
            public string Xml { get; set; }
        }

        public string GetCss()
        {
            string css = "";
            if(this.Parent != null)
                css += this.Parent.GetCss();

            css += "\r\n/* CSS for Template: " + this.Name + "*/\r\n\r\n" + (this.Css?? "");
            return css;
        }

        public string GetScript()
        {
            string script = "";
            if(this.Parent != null)
                script += this.Parent.GetScript();

            script += "\r\n/* JavaScript for Template: " + this.Name + "*/\r\n\r\n" + (this.Script ?? "");
            return script;
        }

        public bool ContainsWorkflow(WorkflowConfiguration config)
        {
            return this.Workflows != null && this.Workflows.Contains(config);
        }

        public void AddWorkflow(WorkflowConfiguration config)
        {
            List<WorkflowConfiguration> workflows = (this.Workflows ?? new WorkflowConfiguration []{}).ToList();
            workflows.Add(config);
            this.Workflows = workflows.ToArray();
        }

        public IEnumerable<PageTemplate> GetAllInheritedTemplates(bool includingMe)
        {
            if (includingMe)
                yield return this;
            
            var t = this;
            while(t.Parent != null)
            {
                t = t.Parent;
                yield return t;
            }
        }
    }
}
